package tool.soft

import akka.stream.Materializer

import java.io.File
import command.CommandExec
import dao._
import models.Tables
import org.joda.time.DateTime
import play.api.mvc.{AnyContent, Request}
import play.twirl.api.Html
import shared.Pojo._
import tool.Pojo._
import tool._
import tool.plot._
import tool.soft.AllSoft.SoftBT

import scala.collection.immutable.SeqMap
import implicits.Implicits._
import models.Tables._
import play.api.data.FormBinding
import tool.softT.{AllSoftBT, DiffAnaSoftBT}
import play.api.i18n.Messages
import play.api.libs.ws.WSClient
import utils.Utils
import upickle.default._

/**
 * Created by yz on 15/9/2020
 */
object LefseAnaSoft extends SoftBT with LefseAnaSoftT {

  override def getResultFileName: String = {
    "Diff_Metabolite.csv"
  }

  override def getFileInfos(workspaceDir: File, index: Int)(implicit matrixFileDataDao: MatrixFileDataDao, messages: Messages): List[FileInfoData] = {
    List(
      FileInfoData("lefse_LDA.xls", messages("lefseLDA")),
      FileInfoData("lefse_LDA_diff.xls", messages("lefseLDADiff")),
      FileInfoData("lefse_LDA.pdf", messages("lefseLDAPdf")),
      FileInfoData("lefse_LDA.cladogram.pdf", messages("lefseLDACladogram")),
      FileInfoData("lefse_LDA.features.pdf", messages("lefseLDAFeatures")),
    )
  }

  override def getResultHtml(missionId: Int)(implicit request: Request[AnyContent], messages: Messages): Html = {
    views.html.user.mission.lefseAnaResult(missionId)
  }

  override def produceConfigFile(workspaceDir: File, index: Int)(implicit request: Request[AnyContent], formBinding: FormBinding) = {
    data.lines().toTxtFile(Tool.getCalculateConfigTxtFile(workspaceDir))
    Utils.t2ConfigFile(workspaceDir, data)
    Tool.producePlotConfigFile(SFormTool.getAllPlotData, Lda, workspaceDir)
    Tool.producePlotConfigFile(SFormTool.getAllPlotData, Cladogram, workspaceDir)
    Tool.producePlotConfigFile(SFormTool.getAllPlotData, Features, workspaceDir)
  }

  def getArg(implicit request: Request[AnyContent], messages: Messages, formBinding: FormBinding): ujson.Value = {
    val yStr = data.y match {
      case "1" => "one-against-one"
      case "0" => messages("y0")
    }
    val argMap = SeqMap(messages("level") -> data.level, messages("a") -> data.a, messages("w") -> data.w,
      messages("l") -> data.l, messages("y") -> yStr)
    writeJs(argMap)
  }

  override def getHtml(missionName: String, missionId: Option[Int])(implicit request: Request[AnyContent], messages: Messages): Html = {
    views.html.user.soft.lefseAna(missionName, missionId)
  }

  override def getMission(implicit request: Request[AnyContent], matrixFileDataDao: MatrixFileDataDao, messages: Messages, formBinding: FormBinding): Tables.MissionRow = {
    val input = List(data.file, data.groupFile)
    val argJson = getArg
    MissionRow(id = 0, missionName = s"${data.missionName}", kind = nameStr, userId = userId,
      startTime = new DateTime(), state = "preparing", arg = argJson, input = input)
  }

  override def produceInputFile(workspaceDir: File)(implicit request: Request[AnyContent], dao: MyDao, formBinding: FormBinding): Any = {
    val rawDataFile =if(data.file.endsWith(".biom")){
      Tool.getOtuTaxaBiomFile(workspaceDir)
    }else{
      Tool.getOtuFile(workspaceDir)
    }
    Tool.produceRawDataFile(userId, data.file, rawDataFile)

    val groupFile = Tool.getGroupFile(workspaceDir)
    Tool.produceRawGroupFile(userId, data.groupFile, groupFile, headerMap = SeqMap("sample" -> "#Sample",
      "classnote" -> "Group"))
  }

  override def data(implicit request: Request[AnyContent], formBinding: FormBinding) = {
    FormTool.lefseAnaForm.bindFromRequest().get
  }

  override def resultDeal(workspaceDir: File, resultDir: File)(implicit ws: WSClient, materializer: Materializer): Unit = {
    super.resultDeal(workspaceDir, resultDir)
    new File(workspaceDir,"tax_summary_a").dirCopyToDir(resultDir)
   List("lefse_format.txt","lefse_input.txt").foreach{fileName=>
     new File(workspaceDir,fileName).fileCopyToDir(resultDir)
   }
  }

  override def getCommandData(workspaceDir: File, resultDir: File, index: Int): List[CommandData] = {
    val rawDataFile = Tool.getOtuTaxaBiomFile(workspaceDir)
    val tableFile = Tool.getOtuFile(workspaceDir)
    val groupFile = Tool.getGroupFile(workspaceDir)
    val value = Utils.configFile2Json(workspaceDir)
    val data =value.transform(reader[LefseAnaData])
    val sumLevel = (1 to data.level.toInt).mkString(",")
    val convertCommand=if(data.file.endsWith(".biom")){
      ""
    }else
      s"""
         |biom convert -i ${tableFile.unixPath} -o ${rawDataFile.unixPath} --table-type='OTU table' --to-json --process-obs-metadata taxonomy
         |""".stripMargin
    val command =
      s"""
         |dos2unix *
         |${convertCommand}
         |${"python".condaPath("py2Env")}  ${new File(Tool.pyPath, "summarize_taxa.py").unixPath} -i ${rawDataFile.unixPath} -o tax_summary_a -L ${sumLevel} -a
         |perl ${new File(Tool.plPath, "plot-lefse.pl").unixPath}  -i tax_summary_a/ -o ./ -m ${groupFile.unixPath} -g Group -l ${data.level}
         |${"python".condaPath("py2Env")} ${new File(Tool.pyPath, "format_input.py").unixPath}  lefse_input.txt lefse_format.txt  -f r -c 1 -u 2 -o 1000000
         |python ${new File(Tool.pyPath, "run_lefse.py").unixPath} lefse_format.txt ./ -a ${data.a} -w ${data.w} -l ${data.l} -y ${data.y} -e 0
         |${"Rscript".condaPath()} ${new File(Tool.rPath, "ida_filter.R").unixPath}  -i lefse_LDA.xls -o lefse_LDA_diff.xls
         |python ${new File(Tool.pyPath, "plot_res.py").unixPath}  lefse_LDA.xls lefse_LDA.pdf --dpi 300 --format pdf --width 10
         |python ${new File(Tool.pyPath, "plot_cladogram.py").unixPath} lefse_LDA.xls lefse_LDA.cladogram.pdf --format pdf --dpi 300 --max_lev 6 --class_legend_font_size 8 --right_space_prop 0.15
         |python ${new File(Tool.pyPath, "plot_features.py").unixPath}  lefse_format.txt lefse_LDA.xls lefse_LDA.features.pdf --format pdf --dpi 300 --width 13
         |convert  -density 300 lefse_LDA.pdf  lefse_LDA.png
         |convert  -density 300 lefse_LDA.cladogram.pdf  lefse_LDA.cladogram.png
         |convert  -density 300 lefse_LDA.features.pdf[0] lefse_LDA.features.png
           """.stripMargin
    List(CommandData(workspaceDir, List(command)))
  }

}

